/*
 * Copyright 2010 - Jeremie Brebec
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.jb.coinche.server.business.transition;

import java.util.Collections;
import java.util.List;

import org.jb.coinche.client.business.message.AcceptCoincheMessage;
import org.jb.coinche.client.business.message.AuctionMessage;
import org.jb.coinche.client.business.message.CoincheMessage;
import org.jb.coinche.client.business.message.SurCoincheMessage;
import org.jb.coinche.client.business.model.Auction;
import org.jb.coinche.client.business.model.AuctionTurn;
import org.jb.coinche.client.business.model.Card;
import org.jb.coinche.client.business.model.CoincheAuction;
import org.jb.coinche.client.business.model.Game;
import org.jb.coinche.client.business.model.Player;
import org.jb.coinche.client.business.model.Round;
import org.jb.coinche.client.business.model.RoundFinished;
import org.jb.coinche.client.business.model.RoundTurn;
import org.jb.coinche.client.business.model.Trump;
import org.jb.coinche.client.business.model.Auction.CoincheMode;
import org.jb.coinche.server.business.ColorComparator;
import org.jb.statemachine.server.Message;
import org.jb.statemachine.server.Transition;
import org.jb.user.client.UserLogin;

import com.google.inject.Inject;
import com.google.inject.Provider;

/**
 * 
 * @author jeremie
 *
 */
public class AuctionTurnTransition implements Transition {

	@Inject @UserLogin
	private Provider<String> user;
	
	/*
	 * Réception d'une nouvelle enchere
	 */
	@Message
	public Object processAuctionMessage( AuctionTurn turn, AuctionMessage msg ) {
		
		String userName = user.get();
		
		Player p = turn.getGame().getPlayer( userName );
		if (p == null)
			throw new IllegalArgumentException("Invalid user");
		
		turn.setAuction( p, msg.getAuction() );
		
		if (turn.isFinished()) {
			/*
			 * Les encheres sont finies
			 */
			if (turn.getCurrentAuction() == null) {
			
				/*
				 * Tous le monde a passé => On recommence
				 */
				RoundFinished rf = new RoundFinished();
				rf.setGame( turn.getGame() );
				
				return rf;
			}
			else
			{
				/*
				 * Creation d'une nouvelle partie, et du premier tour
				 */
				return createRoundTurn( turn.getCurrentAuction(), turn.getGame() );
			}
		}
		
		/*
		 * Sinon, le prochain joueur doit encherir
		 */
		turn.setWaitingPlayer( turn.getGame().getNextPlayer(p) );
		
		return turn;
	}
	
	
	/*
	 * 
	 */
	private RoundTurn createRoundTurn( Auction auction, Game game ) {
		/*
		 * Creation d'une nouvelle partie, et du premier tour
		 */
		Round round = new Round();
		round.setAuction( auction );
		round.setGame( game );
		
		RoundTurn roundTurn = new RoundTurn();
		roundTurn.setCurrentPlayer( game.getNextPlayer(game.getDealer()) );
		roundTurn.setRound( round );
		
		// On tri les cartes en fonction de l'atout
		for( Player player : game.getPlayers() ) {
			sort( player.getCards(), round.getAuction().getTrump() );
		}
		
		return roundTurn;
	}
	
	/*
	 * Coinche
	 */
	@Message
	public CoincheAuction processCoincheMessage( AuctionTurn auctionTurn, CoincheMessage msg ) {
		
		String userName = user.get();
		
		/*
		 * On vérifie que le joueur a bien le droit de coincher
		 */
		Player p = auctionTurn.getGame().getPlayer( userName );
		if (p == null) 
			throw new IllegalArgumentException("Joueur inexistant");
		
		if (p.getTeam().equals( auctionTurn.getCurrentAuction().getTeam()))
			throw new IllegalArgumentException("Impossible de coincher sur son partenaire");
		
		CoincheAuction coinche = new CoincheAuction();
		coinche.setCoincheUser( userName );
		coinche.setAuction( auctionTurn.getCurrentAuction() );
		coinche.setGame( auctionTurn.getGame() );
		
		return coinche;
	}
	
	/*
	 * La coinche a été accepté
	 */
	@Message
	public RoundTurn processAcceptCoincheMessage( CoincheAuction coinche, AcceptCoincheMessage msg ) {
		/*
		 * On commence un nouveau tour
		 */
		Auction auction = coinche.getAuction();
		auction.setCoincheMode( CoincheMode.COINCHE );
		
		return createRoundTurn(auction, coinche.getGame() );
	}
	
	/*
	 * La coinche a été surcoinché
	 */
	@Message
	public RoundTurn processSurCoincheMessage( CoincheAuction coinche, SurCoincheMessage msg ) {
		/*
		 * On commence un nouveau tour
		 */
		Auction auction = coinche.getAuction();
		auction.setCoincheMode( CoincheMode.SURCOINCHE );
		
		return createRoundTurn(auction, coinche.getGame() );
	}
	
	/**
	 * 
	 * @param cards
	 * @param trump
	 */
	public static void sort( List<Card> cards, Trump trump ) {
		Collections.sort(cards, new ColorComparator(trump) );
	}
}
